/*  8 maggio 2012
**  Classe: skype
**  invia messaggi provenienti da Dbus/skype al gestore e riceve tutte le comunicazioni
**  dal gestore/irc inviandole su Skype tramite la funzione invoke
*/

#include <iostream>
#include <string>
using namespace std;

//Librerie per l'uso delle socket
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
//Libreria di gestione delle stringhe
#include <string.h>

#include <glib.h>
#include <dbus/dbus-glib.h>
#include <dbus/dbus-glib-lowlevel.h>

#include <stdlib.h>
#include <stdio.h>

#include <time.h>






class Skype {
        private:
                DBusConnection *bus;                 // dbus handler
                Read (); 
        public:
                Skype ();				// Il costruttore: crea l'handler e lo bounda a skype
                ThreadRead ();          //Legge da Skype e manda al buffer
                Send ();                //Invio del messaggio in Skype
};


/* Costruttore che crea la connessione al dbus e si colllega all'oggetto di skype.*/
Skype :: Skype () : MAX_PACK(512), descr(des) {

  GMainLoop *loop;
  DBusError error;
  dbus_error_init (&error);
  DBusObjectPathVTable vtable;


  ttp->bus = dbus_bus_get (DBUS_BUS_SESSION, &error);

  if (dbus_error_is_set (&error))
      cerr << "[SKYPE-ERROR] Failed to get connection: " << error.message) << endl;


  if (!ttp->bus)
{
      cerr << "[SKYPE-ERROR] Failed to connect to D-BUS: "<< error.message << endl;
      dbus_error_free (&error);
      exit (1);
    }

  // Set up this connection to work in a GLib event loop.
  dbus_connection_setup_with_g_main (ttp->bus, NULL);

  loop = g_main_loop_new (NULL, FALSE);
  dbus_connection_setup_with_g_main (bus, NULL);        // set up te DBus connection
  
	// La funzione che viene evocata per i messaggi in arrivo da dbus
  vtable.message_function = notify_handler;      

	// Si collega a skype! (l'ultimo parametro è un puntatore ad una struct: 
	// sono i parametri che servono alla funzione
  dbus_connection_register_object_path (bus, "/com/Skype/Client", &vtable, NULL);

  // Register with Skype. Use the Skype API 1.2 protocol.
  invoke (bus, "NAME skype2irc", "OK", 20000);
  invoke (bus, "PROTOCOL 3", "OK", 500);
  count << "Skype: Terminato il buongiorno, entriamo nel loop!" << endl;
  
  g_main_loop_run (loop);
  // Fatto! :)
}







/*
Questa è la funzione generica che invia un messaggio a skype tramite dbus.
*/
	
DBusMessage *
invoke (const char *cmd, const char *check,
        int time2wait)
{
  DBusMessage *send;
  DBusMessage *reply;
  const char *ack;
  DBusError errorz;
  dbus_error_init (&errorz);

  send = create_message (cmd);
  // printf("Bus: %p,\n send: %p,\n time2wait: %d,\n Error: %p\n", bus, send, time2wait, &errorz);  

  reply = dbus_connection_send_with_reply_and_block (bus, send, time2wait, &errorz);

  if (dbus_error_is_set (&errorz))
    {
      cerr << "[SKYPE-ERROR] Error: " << errorz.message << endl;
      dbus_error_free (&errorz);
      // exit (1);
    }

  if (reply == NULL)
    {
      // cout << "il reply è null" << endl;
    }
	/* Else: è tutto ok */
  else
    {
      dbus_message_get_args (reply, &errorz, DBUS_TYPE_STRING, &ack,
                             DBUS_TYPE_INVALID);
    }
	
  if (dbus_error_is_set (&errorz))
    {
      cerr << "[SKYPE-ERROR]" << (char *)&errorz.message << endl;
      dbus_error_free (&errorz);
    }


/* Questo serve se vogliamo implementare un check delle risposte di dbus
Praticamente sappiamo che se il messaggio che arriva da DBUS contiene una stringa nota, 
allora sappiamo che è corretto. In questo caso non sappiamo il contenuto delle stringhe di ritorno, quindi 
possiamo implementarlo eventualmente in un momento successivo */
/*
  if (check)
    {
      // Check that Skype's reply is that what expected to be
      if (strstr (check, ack) != 0);    //assert(0);
    }
  else
    {
      // Check for error from Skype itself
      if (strncmp ("ERROR", ack, 5) == 0);      //assert(0);
    }
 
  */
  // Non ho capito bene a cosa servono...
  //dbus_message_unref(send);
  //dbus_message_unref(reply);
  return (reply);
}




/*
Procedimento per sapere come fare a mandare questo alla nostra chat preferita!
Troviamo le chat attive
SEARCH ACTIVECHATS || SEARCH MISSEDCHATS (l'ultimo funziona like a charm)

Una volta individuata la chat, si prosegue con l'invio di messaggi

CHATMESSAGE #truleetz/$salvatore.fresta;99d427e4ea57803f AAOISDJAOSIDJASOID per tesing
CHATMESSAGE  #apesoli.cons.mi/$fpietrosanti;5ab9bbf22cc48685  SARà LA SDRENA FUTURA


*/
void
Send (DBusConnection * bus, char *nick, char *msg)
{
  char canale[] = { "#xxxxxxxxxxxxxxxxxxxxxxxxxx" };
  char sendskype_msg[30000 - 1];
  sprintf (sendskype_msg, "CHATMESSAGE ");
  strncat (sendskype_msg, canale, strlen(canale) );
  strncat (sendskype_msg, " ", 1);
  strncat (sendskype_msg, nick, strlen(nick) );
  strncat (sendskype_msg, ": ", 2);
  strncat (sendskype_msg, msg, strlen(msg) );
  printf ("Sto inviando %s\n", sendskype_msg);
  invoke (bus, sendskype_msg, "SENDING", 500);
}










